/*
 * Galaxium Messenger
 * 
 * Copyright (C) 2009 Philippe Durand <draekz@gmail.com>
 * 
 * License: GNU General Public License (GPL)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
using System;
using System.Collections.Generic;

using Glade;
using G=Gtk;

using Galaxium.Protocol;
using Galaxium.Core;
using Galaxium.Gui;
using Galaxium.Gui.GtkGui;
using Galaxium.Protocol.Gui;

using Anculus.Core;

namespace Galaxium.Gui.GtkGui
{
	public enum FilterType { ByDate = 0, ByRange, LastHour, LastDay, LastWeek, LastMonth, LastYear, All };
	
	public sealed class ViewHistoryDialog
	{
		[Widget("ViewLogsDialog")] G.Dialog _dialog;
		[Widget("MessageBox")] G.HBox _messageBox;
		[Widget("FilterBox")] G.HBox _filterBox;
		[Widget("StartCalendar")] G.Calendar _startCalendar;
		[Widget("EndCalendar")] G.Calendar _endCalendar;
		[Widget("CloseButton")] G.Button _closeButton;
		[Widget("SaveButton")] G.Button _saveButton;
		[Widget("ClearButton")] G.Button _clearButton;
		
		private ImageComboBox<FilterType> _filterCombo;
		private MessageDisplayWidget _messageDisplay;
		private IChatWidget<G.Widget> _chatWidget;
		private IConversation _conversation;
		
		public ViewHistoryDialog (IConversation conversation, IChatWidget<G.Widget> chatWidget)
		{
			ThrowUtility.ThrowIfNull ("conversation", conversation);
			
			_conversation = conversation;
			_chatWidget = chatWidget;
			
			XML gxml = new XML (GladeUtility.GetGladeResourceStream (typeof (ViewHistoryDialog).Assembly, "ViewHistoryDialog.glade"), null, null);
			gxml.Autoconnect (this);
			
			_dialog.Icon = IconUtility.GetIcon ("galaxium-preferences-logging", IconSizes.Small);
			
			_dialog.Title = "View Logs: "+conversation.PrimaryContact.DisplayName;
			
			// Setup the window how it should look based on preferences.
			_messageDisplay = new MessageDisplayWidget (_conversation);
			_messageBox.PackStart (_messageDisplay, true, true, 0);
			
			_filterCombo = new ImageComboBox<FilterType> (
				new ImageComboTextLookup<FilterType> (FilterTextLookup),
				null //new ImageComboPixbufLookup<int> (FilterImageLookup)
			);
			
			_filterCombo.Append (FilterType.ByDate);
			_filterCombo.Append (FilterType.ByRange);
			_filterCombo.AppendSeperator ();
			_filterCombo.Append (FilterType.LastHour);
			_filterCombo.Append (FilterType.LastDay);
			_filterCombo.Append (FilterType.LastWeek);
			_filterCombo.Append (FilterType.LastMonth);
			_filterCombo.Append (FilterType.LastYear);
			_filterCombo.AppendSeperator ();
			_filterCombo.Append (FilterType.All);
			
			_filterCombo.Active = 0;
			_filterCombo.Changed += HandleFilterChanged;
			_filterBox.PackStart (_filterCombo, true, true, 0);
			
			_startCalendar.Date = DateTime.Today.AddDays(-1);
			_startCalendar.DaySelected += HandleStartDaySelected;
			_endCalendar.Date = DateTime.Today;
			_endCalendar.DaySelected += HandleEndDaySelected;
			
			UpdateStates();
			UpdateMessages();
			
			_dialog.ShowAll();
		}
		
		public int Run ()
		{
			return _dialog.Run ();
		}
		
		public void Destroy ()
		{
			_dialog.Destroy ();
		}
		
		private void HandleStartDaySelected(object sender, EventArgs e)
		{
			UpdateMessages();
		}
		
		private void HandleEndDaySelected(object sender, EventArgs e)
		{
			UpdateMessages();
		}
		
		private string FilterTextLookup (FilterType item)
		{
			switch (item)
			{
				case FilterType.ByDate:
					return "Show by date";
				
				case FilterType.ByRange:
					return "Show by date range";
				
				case FilterType.LastHour:
					return "Show the last hour";
				
				case FilterType.LastDay:
					return "Show the last day";
				
				case FilterType.LastWeek:
					return "Show the last week";
				
				case FilterType.LastMonth:
					return "Show the last month";
				
				case FilterType.LastYear:
					return "Show the last year";
				
				case FilterType.All:
					return "Show all";
				
				default:
					return "Error!";
			}
		}
		
		private void HandleFilterChanged(object sender, EventArgs e)
		{
			UpdateStates ();
			UpdateMessages();
		}
		
		private void UpdateMessages ()
		{
			_messageDisplay.Clear();
			
			IEnumerable<ConversationLogEntry> entries = null;
			DateTime from = DateTime.Now;
			DateTime to = DateTime.Now;
			
			switch (_filterCombo.GetSelectedItem())
			{
				case FilterType.ByDate:
					from = _startCalendar.Date;
					to = _startCalendar.Date.AddHours(24);
					break;
				
				case FilterType.ByRange:
					from = _startCalendar.Date;
					to = _endCalendar.Date.AddHours(24);
					break;
				
				case FilterType.LastHour:
					from = DateTime.Now.AddHours(-1);
					to = DateTime.Now;
					break;
				
				case FilterType.LastDay:
					from = DateTime.Now.AddDays(-1);
					to = DateTime.Now;
					break;
				
				case FilterType.LastWeek:
					from = DateTime.Now.AddDays(-7);
					to = DateTime.Now;
					break;
				
				case FilterType.LastMonth:
					from = DateTime.Now.AddMonths(-1);
					to = DateTime.Now;
					break;
				
				case FilterType.LastYear:
					from = DateTime.Now.AddYears(-1);
					to = DateTime.Now;
					break;
				
				case FilterType.All:
					from = DateTime.MinValue;
					to = DateTime.Now;
					break;
			}
			
			// Now that we know how much, lets grab the entries.
			entries = _conversation.ConversationLog.GetRangeEntries(from, to);
			
			if (entries != null)
			{
				DateTime currentDate = DateTime.MinValue;
				
				foreach (ConversationLogEntry entry in entries)
				{
					if (currentDate.Date != entry.TimeStamp.Date)
					{
						currentDate = entry.TimeStamp.Date;
						_messageDisplay.AddMisc (MessageFlag.InfoChange, "Showing log entries for: "+currentDate.ToLongDateString());
					}
					
					var entity = (String.IsNullOrEmpty (entry.UniqueIdentifier) && String.IsNullOrEmpty (entry.DisplayName)) ? _conversation.Session.Account : _chatWidget.GetEntity (entry.UniqueIdentifier, entry.DisplayName);
						
					IMessage msg = new Message ((entry.IsEvent ? MessageFlag.Event : MessageFlag.Message) | MessageFlag.History, entity, null, entry.TimeStamp);
					msg.SetMarkup (entry.Message, null);
					
					_messageDisplay.AddMessage (msg);
				}
			}
		}
		
		private void UpdateStates ()
		{
			switch (_filterCombo.GetSelectedItem())
			{
				case FilterType.ByDate:
					_startCalendar.Sensitive = true;
					_endCalendar.Sensitive = false;
					break;
				
				case FilterType.ByRange:
					_startCalendar.Sensitive = true;
					_endCalendar.Sensitive = true;
					break;
				
				case FilterType.LastHour:
				case FilterType.LastDay:
				case FilterType.LastWeek:
				case FilterType.LastMonth:
				case FilterType.LastYear:
				case FilterType.All:
					_startCalendar.Sensitive = false;
					_endCalendar.Sensitive = false;
					break;
			}
		}
	}
}
